home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Unix / Shells / tcsh / Source / tw.init.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-02-21  |  20.5 KB  |  985 lines

  1. /* $Header: /u/christos/src/tcsh-6.03/RCS/tw.init.c,v 3.13 1992/10/05 02:41:30 christos Exp $ */
  2. /*
  3.  * tw.init.c: Handle lists of things to complete
  4.  */
  5. /*-
  6.  * Copyright (c) 1980, 1991 The Regents of the University of California.
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  * 1. Redistributions of source code must retain the above copyright
  13.  *    notice, this list of conditions and the following disclaimer.
  14.  * 2. Redistributions in binary form must reproduce the above copyright
  15.  *    notice, this list of conditions and the following disclaimer in the
  16.  *    documentation and/or other materials provided with the distribution.
  17.  * 3. All advertising materials mentioning features or use of this software
  18.  *    must display the following acknowledgement:
  19.  *    This product includes software developed by the University of
  20.  *    California, Berkeley and its contributors.
  21.  * 4. Neither the name of the University nor the names of its contributors
  22.  *    may be used to endorse or promote products derived from this software
  23.  *    without specific prior written permission.
  24.  *
  25.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  26.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  27.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  28.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  29.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  30.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  31.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  32.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  33.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  34.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  35.  * SUCH DAMAGE.
  36.  */
  37. #include "sh.h"
  38.  
  39. RCSID("$Id: tw.init.c,v 3.13 1992/10/05 02:41:30 christos Exp $")
  40.  
  41. #include "tw.h"
  42. #include "ed.h"
  43. #include "tc.h"
  44. #include "sh.proc.h"
  45.  
  46. #if !defined(NSIG) && defined(SIGMAX)
  47. # define NSIG (SIGMAX+1)
  48. #endif /* !NSIG && SIGMAX */
  49. #if !defined(NSIG) && defined(_NSIG)
  50. # define NSIG _NSIG
  51. #endif /* !NSIG && _NSIG */
  52.  
  53. #define TW_INCR    128
  54.  
  55. typedef struct {
  56.     Char **list,             /* List of command names    */
  57.       *buff;            /* Space holding command names    */
  58.     int    nlist,             /* Number of items        */
  59.            nbuff,            /* Current space in name buf    */
  60.            tlist,            /* Total space in list        */
  61.        tbuff;            /* Total space in name buf    */
  62. } stringlist_t;
  63.  
  64.  
  65. static struct varent *tw_vptr = NULL;    /* Current shell variable     */
  66. static Char **tw_env = NULL;        /* Current environment variable */
  67. static Char  *tw_word;            /* Current word pointer        */
  68. static struct KeyFuncs *tw_bind = NULL;    /* List of the bindings        */
  69. #ifndef HAVENOLIMIT
  70. static struct limits *tw_limit = NULL;    /* List of the resource limits    */
  71. #endif /* HAVENOLIMIT */
  72. static int tw_index = 0;        /* signal and job index        */
  73. static DIR   *tw_dir_fd = NULL;        /* Current directory descriptor    */
  74. static Char   tw_retname[MAXPATHLEN+1];    /* Return buffer        */
  75. static int    tw_cmd_got = 0;        /* What we need to do        */
  76. static stringlist_t tw_cmd  = { NULL, NULL, 0, 0, 0, 0 };
  77. static stringlist_t tw_item = { NULL, NULL, 0, 0, 0, 0 };
  78. #define TW_FL_CMD    0x01
  79. #define TW_FL_ALIAS    0x02
  80. #define TW_FL_BUILTIN    0x04
  81. #define TW_FL_SORT    0x08
  82. #define TW_FL_REL    0x10
  83.  
  84. static struct {                /* Current element pointer    */
  85.     int    cur;                /* Current element number    */
  86.     Char **pathv;            /* Current element in path    */
  87.     DIR   *dfd;                /* Current directory descriptor    */
  88. } tw_cmd_state;
  89.  
  90.  
  91. #ifdef BSDSIGS
  92. static sigmask_t tw_omask;
  93. # define TW_HOLD()    tw_omask = sigblock(sigmask(SIGINT))
  94. # define TW_RELS()    (void) sigsetmask(tw_omask)
  95. #else /* !BSDSIGS */
  96. # define TW_HOLD()    (void) sighold(SIGINT)
  97. # define TW_RELS()    (void) sigrelse(SIGINT)
  98. #endif /* BSDSIGS */
  99.  
  100. #define SETDIR(dfd) \
  101.     { \
  102.     tw_dir_fd = dfd; \
  103.     if (tw_dir_fd != NULL) \
  104.         rewinddir(tw_dir_fd); \
  105.     }
  106.  
  107. #define CLRDIR(dfd) \
  108.     if (dfd != NULL) { \
  109.     TW_HOLD(); \
  110.     (void) closedir(dfd); \
  111.     dfd = NULL; \
  112.     TW_RELS(); \
  113.     }
  114.  
  115. static Char    *tw_str_add        __P((stringlist_t *, int));
  116. static void     tw_str_free        __P((stringlist_t *));
  117. static Char     *tw_dir_next        __P((DIR *));
  118. static void     tw_cmd_add         __P((Char *name));
  119. static void      tw_cmd_cmd        __P((void));
  120. static void     tw_cmd_builtin        __P((void));
  121. static void     tw_cmd_alias        __P((void));
  122. static void     tw_cmd_sort        __P((void));
  123. static void      tw_vptr_start        __P((struct varent *));
  124.  
  125.  
  126. /* tw_str_add():
  127.  *    Add an item to the string list
  128.  */
  129. static Char *
  130. tw_str_add(sl, len)
  131.     stringlist_t *sl;
  132.     int len;
  133. {
  134.     Char *ptr;
  135.  
  136.     if (sl->tlist <= sl->nlist) {
  137.     TW_HOLD();
  138.     sl->tlist += TW_INCR;
  139.     sl->list = sl->list ? 
  140.             (Char **) xrealloc((ptr_t) sl->list, 
  141.                        (size_t) (sl->tlist * sizeof(Char *))) :
  142.             (Char **) xmalloc((size_t) (sl->tlist * sizeof(Char *)));
  143.     TW_RELS();
  144.     }
  145.     if (sl->tbuff <= sl->nbuff + len) {
  146.     int i;
  147.     ptr = sl->buff;
  148.  
  149.     TW_HOLD();
  150.     sl->tbuff += TW_INCR + len;
  151.     sl->buff = sl->buff ? 
  152.             (Char *) xrealloc((ptr_t) sl->buff, 
  153.                       (size_t) (sl->tbuff * sizeof(Char))) :
  154.             (Char *) xmalloc((size_t) (sl->tbuff * sizeof(Char)));
  155.     /* Re-thread the new pointer list, if changed */
  156.     if (ptr != NULL && ptr != sl->buff) {
  157.         int offs = sl->buff - ptr;
  158.         for (i = 0; i < sl->nlist; i++)
  159.         sl->list[i] += offs;
  160.     }
  161.     TW_RELS();
  162.     }
  163.     ptr = sl->list[sl->nlist++] = &sl->buff[sl->nbuff];
  164.     sl->nbuff += len;
  165.     return ptr;
  166. } /* tw_str_add */
  167.  
  168.  
  169. /* tw_str_free():
  170.  *    Free a stringlist
  171.  */
  172. static void
  173. tw_str_free(sl)
  174.     stringlist_t *sl;
  175. {
  176.     TW_HOLD();
  177.     if (sl->list) {
  178.     xfree((ptr_t) sl->list);
  179.     sl->list = NULL;
  180.     sl->tlist = sl->nlist = 0;
  181.     }
  182.     if (sl->buff) {
  183.     xfree((ptr_t) sl->buff);
  184.     sl->buff = NULL;
  185.     sl->tbuff = sl->nbuff = 0;
  186.     }
  187.     TW_RELS();
  188. } /* end tw_str_free */
  189.  
  190.  
  191. static Char *
  192. tw_dir_next(dfd)
  193.     DIR *dfd;
  194. {
  195.     register struct dirent *dirp;
  196.  
  197.     if (dfd == NULL)
  198.     return NULL;
  199.  
  200.     if ((dirp = readdir(dfd)) != NULL) {
  201.     (void) Strcpy(tw_retname, str2short(dirp->d_name));
  202.     return (tw_retname);
  203.     }
  204.     return NULL;
  205. } /* end tw_dir_next */
  206.  
  207.  
  208. /* tw_cmd_add():
  209.  *    Add the name to the command list
  210.  */
  211. static void
  212. tw_cmd_add(name)
  213.     Char *name;
  214. {
  215.     int len;
  216.  
  217.     if (name[0] == '#' || name[0] == '.')    /* emacs temp's, .files    */
  218.     return;
  219.     len = Strlen(name) + 2;
  220.     if (name[len - 3] == '~')            /* No emacs backups */
  221.     return;
  222.     
  223.     (void) Strcpy(tw_str_add(&tw_cmd, len), name);
  224. } /* end tw_cmd_add */
  225.  
  226.  
  227. /* tw_cmd_free():
  228.  *    Free the command list
  229.  */
  230. void
  231. tw_cmd_free()
  232. {
  233.     CLRDIR(tw_dir_fd)
  234.     tw_str_free(&tw_cmd);
  235.     tw_cmd_got = 0;
  236. } /* end tw_cmd_free */
  237.  
  238. /* tw_cmd_cmd():
  239.  *    Add system commands to the command list
  240.  */
  241. static void
  242. tw_cmd_cmd()
  243. {
  244.     register DIR *dirp;
  245.     register struct dirent *dp;
  246.     register Char *dir = NULL, *name;
  247.     register Char **pv;
  248.     struct varent *v = adrof(STRpath);
  249.     struct varent *recexec = adrof(STRrecognize_only_executables);
  250.  
  251.  
  252.     if (v == NULL) /* if no path */
  253.     return;
  254.  
  255.     for (pv = v->vec; *pv; pv++) {
  256.     if (pv[0][0] != '/') {
  257.         tw_cmd_got |= TW_FL_REL;
  258.         continue;
  259.     }
  260.  
  261.     if ((dirp = opendir(short2str(*pv))) == NULL)
  262.         continue;
  263.  
  264.     if (recexec)
  265.         dir = Strspl(*pv, STRslash);
  266.     while ((dp = readdir(dirp)) != NULL) {
  267.         /* the call to executable() may make this a bit slow */
  268.         name = str2short(dp->d_name);
  269.         if (dp->d_ino == 0 || (recexec && !executable(dir, name, 0)))
  270.         continue;
  271.         tw_cmd_add(name);
  272.     }
  273.     (void) closedir(dirp);
  274.     if (recexec)
  275.         xfree((ptr_t) dir);
  276.     }
  277. } /* end tw_cmd_cmd */
  278.  
  279.  
  280. /* tw_cmd_builtin():
  281.  *    Add builtins to the command list
  282.  */
  283. static void
  284. tw_cmd_builtin()
  285. {
  286.     register struct biltins *bptr;
  287.  
  288.     for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++)
  289.     if (bptr->bname)
  290.         tw_cmd_add(str2short(bptr->bname));
  291. } /* end tw_cmd_builtin */
  292.  
  293.  
  294. /* tw_cmd_alias():
  295.  *    Add aliases to the command list
  296.  */
  297. static void
  298. tw_cmd_alias()
  299. {
  300.     register struct varent *p;
  301.     register struct varent *c;
  302.  
  303.     p = &aliases;
  304.     for (;;) {
  305.     while (p->v_left)
  306.         p = p->v_left;
  307. x:
  308.     if (p->v_parent == 0) /* is it the header? */
  309.         return;
  310.     if (p->v_name)
  311.         tw_cmd_add(p->v_name);
  312.     if (p->v_right) {
  313.         p = p->v_right;
  314.         continue;
  315.     }
  316.     do {
  317.         c = p;
  318.         p = p->v_parent;
  319.     } while (p->v_right == c);
  320.     goto x;
  321.     }
  322. } /* end tw_cmd_alias */
  323.  
  324.  
  325. /* tw_cmd_sort():
  326.  *    Sort the command list removing duplicate elements
  327.  */
  328. static void
  329. tw_cmd_sort()
  330. {
  331.     int fwd, i;
  332.  
  333.     TW_HOLD();
  334.     /* sort the list. */
  335.     qsort((ptr_t) tw_cmd.list, (size_t) tw_cmd.nlist, sizeof(Char *), 
  336.       (int (*) __P((const void *, const void *))) fcompare);
  337.  
  338.     /* get rid of multiple entries */
  339.     for (i = 0, fwd = 0; i < tw_cmd.nlist - 1; i++) {
  340.     if (Strcmp(tw_cmd.list[i], tw_cmd.list[i + 1]) == 0) /* garbage */
  341.         fwd++;        /* increase the forward ref. count */
  342.     else if (fwd) 
  343.         tw_cmd.list[i - fwd] = tw_cmd.list[i];
  344.     }
  345.     /* Fix fencepost error -- Theodore Ts'o <tytso@athena.mit.edu> */
  346.     if (fwd)
  347.     tw_cmd.list[i - fwd] = tw_cmd.list[i];
  348.     tw_cmd.nlist -= fwd;
  349.     TW_RELS();
  350. } /* end tw_cmd_sort */
  351.  
  352.  
  353. /* tw_cmd_start():
  354.  *    Get the command list and sort it, if not done yet.
  355.  *    Reset the current pointer to the beginning of the command list
  356.  */
  357. /*ARGSUSED*/
  358. void
  359. tw_cmd_start(dfd, pat)
  360.     DIR *dfd;
  361.     Char *pat;
  362. {
  363.     static Char *defpath[] = { STRNULL, 0 };
  364.     SETDIR(dfd)
  365.     if ((tw_cmd_got & TW_FL_CMD) == 0) {
  366.     tw_cmd_free();
  367.     tw_cmd_cmd();
  368.     tw_cmd_got |= TW_FL_CMD;
  369.     }
  370.     if ((tw_cmd_got & TW_FL_ALIAS) == 0) {
  371.     tw_cmd_alias();
  372.     tw_cmd_got &= ~TW_FL_SORT;
  373.     tw_cmd_got |= TW_FL_ALIAS;
  374.     }
  375.     if ((tw_cmd_got & TW_FL_BUILTIN) == 0) {
  376.     tw_cmd_builtin();
  377.     tw_cmd_got &= ~TW_FL_SORT;
  378.     tw_cmd_got |= TW_FL_BUILTIN;
  379.     }
  380.     if ((tw_cmd_got & TW_FL_SORT) == 0) {
  381.     tw_cmd_sort();
  382.     tw_cmd_got |= TW_FL_SORT;
  383.     }
  384.  
  385.     tw_cmd_state.cur = 0;
  386.     CLRDIR(tw_cmd_state.dfd)
  387.     if (tw_cmd_got & TW_FL_REL) {
  388.     struct varent *vp = adrof(STRpath);
  389.     if (vp && vp->vec)
  390.         tw_cmd_state.pathv = vp->vec;
  391.     else
  392.         tw_cmd_state.pathv = defpath;
  393.     }
  394.     else 
  395.     tw_cmd_state.pathv = defpath;
  396. } /* tw_cmd_start */
  397.  
  398.  
  399. /* tw_cmd_next():
  400.  *    Return the next element in the command list or
  401.  *    Look for commands in the relative path components
  402.  */
  403. Char *
  404. tw_cmd_next(dir, flags)
  405.     Char *dir;
  406.     int  *flags;
  407. {
  408.     Char *ptr = NULL;
  409.  
  410.     if (tw_cmd_state.cur < tw_cmd.nlist) {
  411.     *flags = TW_DIR_OK;
  412.     return tw_cmd.list[tw_cmd_state.cur++];
  413.     }
  414.  
  415.     /*
  416.      * We need to process relatives in the path.
  417.      */
  418.     while (((tw_cmd_state.dfd == NULL) ||
  419.         ((ptr = tw_dir_next(tw_cmd_state.dfd)) == NULL)) &&
  420.        (*tw_cmd_state.pathv != NULL)) {
  421.  
  422.         CLRDIR(tw_cmd_state.dfd)
  423.  
  424.     while (*tw_cmd_state.pathv && tw_cmd_state.pathv[0][0] == '/')
  425.         tw_cmd_state.pathv++;
  426.     if ((ptr = *tw_cmd_state.pathv) != 0) {
  427.         /*
  428.          * We complete directories only on '.' should that
  429.          * be changed?
  430.          */
  431.         if (ptr[0] == '\0' || (ptr[0] == '.' && ptr[1] == '\0')) {
  432.         *dir = '\0';
  433.         tw_cmd_state.dfd = opendir(".");
  434.         *flags = TW_DIR_OK | TW_EXEC_CHK;    
  435.         }
  436.         else {
  437.         copyn(dir, *tw_cmd_state.pathv, FILSIZ);
  438.         catn(dir, STRslash, FILSIZ);
  439.         tw_cmd_state.dfd = opendir(short2str(*tw_cmd_state.pathv));
  440.         *flags = TW_EXEC_CHK;
  441.         }
  442.         tw_cmd_state.pathv++;
  443.     }
  444.     }
  445.     return ptr;
  446. } /* end tw_cmd_next */
  447.  
  448.  
  449. /* tw_vptr_start():
  450.  *    Find the first variable in the variable list
  451.  */
  452. static void
  453. tw_vptr_start(c)
  454.     struct varent *c;
  455. {
  456.     tw_vptr = c;        /* start at beginning of variable list */
  457.  
  458.     for (;;) {
  459.     while (tw_vptr->v_left)
  460.         tw_vptr = tw_vptr->v_left;
  461. x:
  462.     if (tw_vptr->v_parent == 0) {    /* is it the header? */
  463.         tw_vptr = NULL;
  464.         return;
  465.     }
  466.     if (tw_vptr->v_name)
  467.         return;        /* found first one */
  468.     if (tw_vptr->v_right) {
  469.         tw_vptr = tw_vptr->v_right;
  470.         continue;
  471.     }
  472.     do {
  473.         c = tw_vptr;
  474.         tw_vptr = tw_vptr->v_parent;
  475.     } while (tw_vptr->v_right == c);
  476.     goto x;
  477.     }
  478. } /* end tw_shvar_start */
  479.  
  480.  
  481. /* tw_shvar_next():
  482.  *    Return the next shell variable
  483.  */
  484. /*ARGSUSED*/
  485. Char *
  486. tw_shvar_next(dir, flags)
  487.     Char *dir;
  488.     int     *flags;
  489. {
  490.     register struct varent *p;
  491.     register struct varent *c;
  492.     register Char *cp;
  493.  
  494.     if ((p = tw_vptr) == NULL)
  495.     return (NULL);        /* just in case */
  496.  
  497.     cp = p->v_name;        /* we know that this name is here now */
  498.  
  499.     /* now find the next one */
  500.     for (;;) {
  501.     if (p->v_right) {    /* if we can go right */
  502.         p = p->v_right;
  503.         while (p->v_left)
  504.         p = p->v_left;
  505.     }
  506.     else {            /* else go up */
  507.         do {
  508.         c = p;
  509.         p = p->v_parent;
  510.         } while (p->v_right == c);
  511.     }
  512.     if (p->v_parent == 0) {    /* is it the header? */
  513.         tw_vptr = NULL;
  514.         return (cp);
  515.     }
  516.     if (p->v_name) {
  517.         tw_vptr = p;    /* save state for the next call */
  518.         return (cp);
  519.     }
  520.     }
  521. } /* end tw_shvar_next */
  522.  
  523.  
  524. /* tw_envvar_next():
  525.  *    Return the next environment variable
  526.  */
  527. /*ARGSUSED*/
  528. Char *
  529. tw_envvar_next(dir, flags)
  530.     Char *dir;
  531.     int *flags;
  532. {
  533.     Char   *ps, *pd;
  534.  
  535.     if (tw_env == NULL || *tw_env == NULL)
  536.     return (NULL);
  537.     for (ps = *tw_env, pd = tw_retname;
  538.      *ps && *ps != '=' && pd <= &tw_retname[MAXPATHLEN]; *pd++ = *ps++)
  539.     continue;
  540.     *pd = '\0';
  541.     tw_env++;
  542.     return (tw_retname);
  543. } /* end tw_envvar_next */
  544.  
  545.  
  546. /* tw_var_start():
  547.  *    Begin the list of the shell and environment variables
  548.  */
  549. /*ARGSUSED*/
  550. void
  551. tw_var_start(dfd, pat)
  552.     DIR *dfd;
  553.     Char *pat;
  554. {
  555.     SETDIR(dfd)
  556.     tw_vptr_start(&shvhed);
  557.     tw_env = STR_environ;
  558. } /* end tw_var_start */
  559.  
  560.  
  561. /* tw_alias_start():
  562.  *    Begin the list of the shell aliases
  563.  */
  564. /*ARGSUSED*/
  565. void
  566. tw_alias_start(dfd, pat)
  567.     DIR *dfd;
  568.     Char *pat;
  569. {
  570.     SETDIR(dfd)
  571.     tw_vptr_start(&aliases);
  572.     tw_env = NULL;
  573. } /* tw_alias_start */
  574.  
  575.  
  576. /* tw_complete_start():
  577.  *    Begin the list of completions
  578.  */
  579. /*ARGSUSED*/
  580. void
  581. tw_complete_start(dfd, pat)
  582.     DIR *dfd;
  583.     Char *pat;
  584. {
  585.     extern struct varent completions;
  586.     SETDIR(dfd)
  587.     tw_vptr_start(&completions);
  588.     tw_env = NULL;
  589. } /* end tw_complete_start */
  590.  
  591.  
  592. /* tw_var_next():
  593.  *    Return the next shell or environment variable
  594.  */
  595. Char *
  596. tw_var_next(dir, flags)
  597.     Char *dir;
  598.     int  *flags;
  599. {
  600.     Char *ptr = NULL;
  601.  
  602.     if (tw_vptr)
  603.     ptr = tw_shvar_next(dir, flags);
  604.     if (!ptr && tw_env)
  605.     ptr = tw_envvar_next(dir, flags);
  606.     return ptr;
  607. } /* end tw_var_next */
  608.  
  609.  
  610. /* tw_logname_start():
  611.  *    Initialize lognames to the beginning of the list
  612.  */
  613. /*ARGSUSED*/
  614. void 
  615. tw_logname_start(dfd, pat)
  616.     DIR *dfd;
  617.     Char *pat;
  618. {
  619.     SETDIR(dfd)
  620. #ifndef _VMS_POSIX
  621.     (void) setpwent();    /* Open passwd file */
  622. #endif /* atp vmsposix */
  623. } /* end tw_logname_start */
  624.  
  625.  
  626. /* tw_logname_next():
  627.  *    Return the next entry from the passwd file
  628.  */
  629. /*ARGSUSED*/
  630. Char *
  631. tw_logname_next(dir, flags)
  632.     Char *dir;
  633.     int  *flags;
  634. {
  635.     static Char retname[MAXPATHLEN];
  636.     struct passwd *pw;
  637.     /*
  638.      * We don't want to get interrupted inside getpwent()
  639.      * because the yellow pages code is not interruptible,
  640.      * and if we call endpwent() immediatetely after
  641.      * (in pintr()) we may be freeing an invalid pointer
  642.      */
  643.     TW_HOLD();
  644. #ifndef _VMS_POSIX
  645.     /* ISC does not declare getpwent()? */
  646.     pw = (struct passwd *) getpwent();
  647. #endif /* atp vmsposix */
  648.     TW_RELS();
  649.  
  650.     if (pw == NULL) {
  651. #ifdef YPBUGS
  652.     fix_yp_bugs();
  653. #endif
  654.     return (NULL);
  655.     }
  656.     (void) Strcpy(retname, str2short(pw->pw_name));
  657.     return (retname);
  658. } /* end tw_logname_next */
  659.  
  660.  
  661. /* tw_logname_end():
  662.  *    Close the passwd file to finish th logname list
  663.  */
  664. void
  665. tw_logname_end()
  666. {
  667. #ifdef YPBUGS
  668.     fix_yp_bugs();
  669. #endif
  670. #ifndef _VMS_POSIX
  671.    (void) endpwent();
  672. #endif /* atp vmsposix */
  673. } /* end tw_logname_end */
  674.  
  675.  
  676. /* tw_file_start():
  677.  *    Initialize the directory for the file list
  678.  */
  679. /*ARGSUSED*/
  680. void
  681. tw_file_start(dfd, pat)
  682.     DIR *dfd;
  683.     Char *pat;
  684. {
  685.     struct varent *vp;
  686.     SETDIR(dfd)
  687.     if ((vp = adrof(STRcdpath)) != NULL)
  688.     tw_env = vp->vec;
  689. } /* end tw_file_start */
  690.  
  691.  
  692. /* tw_file_next():
  693.  *    Return the next file in the directory 
  694.  */
  695. Char *
  696. tw_file_next(dir, flags)
  697.     Char *dir;
  698.     int  *flags;
  699. {
  700.     Char *ptr = tw_dir_next(tw_dir_fd);
  701.     if (ptr == NULL && (*flags & TW_DIR_OK) != 0) {
  702.     CLRDIR(tw_dir_fd)
  703.     while (tw_env && *tw_env)
  704.         if ((tw_dir_fd = opendir(short2str(*tw_env))) != NULL)
  705.         break;
  706.         else
  707.         tw_env++;
  708.         
  709.     if (tw_dir_fd) {
  710.         copyn(dir, *tw_env++, MAXPATHLEN);
  711.         catn(dir, STRslash, MAXPATHLEN);
  712.         ptr = tw_dir_next(tw_dir_fd);
  713.     }
  714.     }
  715.     return ptr;
  716. } /* end tw_file_next */
  717.  
  718.  
  719. /* tw_dir_end():
  720.  *    Clear directory related lists
  721.  */
  722. void
  723. tw_dir_end()
  724. {
  725.    CLRDIR(tw_dir_fd)
  726.    CLRDIR(tw_cmd_state.dfd)
  727. } /* end tw_dir_end */
  728.  
  729.  
  730. /* tw_item_free():
  731.  *    Free the item list
  732.  */
  733. void
  734. tw_item_free()
  735. {
  736.     tw_str_free(&tw_item);
  737. } /* end tw_item_free */
  738.  
  739.  
  740. /* tw_item_get(): 
  741.  *    Return the list of items 
  742.  */
  743. Char **
  744. tw_item_get()
  745. {
  746.     return tw_item.list;
  747. } /* end tw_item_get */
  748.  
  749.  
  750. /* tw_item_add():
  751.  *    Return a new item
  752.  */
  753. Char *
  754. tw_item_add(len)
  755.     int len;
  756. {
  757.      return tw_str_add(&tw_item, len);
  758. } /* tw_item_add */
  759.  
  760.  
  761. /* tw_item_find():
  762.  *      Find the string if it exists in the item list 
  763.  *    end return it.
  764.  */
  765. Char *
  766. tw_item_find(str)
  767.     Char    *str;
  768. {
  769.     int i;
  770.  
  771.     if (tw_item.list == NULL || str == NULL)
  772.     return NULL;
  773.  
  774.     for (i = 0; i < tw_item.nlist; i++)
  775.     if (tw_item.list[i] != NULL && Strcmp(tw_item.list[i], str) == 0)
  776.         return tw_item.list[i];
  777.     return NULL;
  778. } /* end tw_item_find */
  779.  
  780.  
  781. /* tw_vl_start():
  782.  *    Initialize a variable list
  783.  */
  784. void
  785. tw_vl_start(dfd, pat)
  786.     DIR *dfd;
  787.     Char *pat;
  788. {
  789.     SETDIR(dfd)
  790.     if ((tw_vptr = adrof(pat)) != NULL) {
  791.     tw_env = tw_vptr->vec;
  792.     tw_vptr = NULL;
  793.     }
  794.     else
  795.     tw_env = NULL;
  796. } /* end tw_vl_start */
  797.  
  798.  
  799. /*
  800.  * Initialize a word list
  801.  */
  802. void
  803. tw_wl_start(dfd, pat)
  804.     DIR *dfd;
  805.     Char *pat;
  806. {
  807.     SETDIR(dfd);
  808.     tw_word = pat;
  809. } /* end tw_wl_start */
  810.  
  811.  
  812. /*
  813.  * Return the next word from the word list
  814.  */
  815. /*ARGSUSED*/
  816. Char *
  817. tw_wl_next(dir, flags)
  818.     Char *dir;
  819.     int *flags;
  820. {
  821.     if (tw_word == NULL || tw_word[0] == '\0')
  822.     return NULL;
  823.     
  824.     while (*tw_word && Isspace(*tw_word)) tw_word++;
  825.  
  826.     for (dir = tw_word; *tw_word && !Isspace(*tw_word); tw_word++)
  827.     continue;
  828.     if (*tw_word)
  829.     *tw_word++ = '\0';
  830.     return *dir ? dir : NULL;
  831. } /* end tw_wl_next */
  832.  
  833.  
  834. /* tw_bind_start():
  835.  *    Begin the list of the shell bindings
  836.  */
  837. /*ARGSUSED*/
  838. void
  839. tw_bind_start(dfd, pat)
  840.     DIR *dfd;
  841.     Char *pat;
  842. {
  843.     SETDIR(dfd)
  844.     tw_bind = FuncNames;
  845. } /* end tw_bind_start */
  846.  
  847.  
  848. /* tw_bind_next():
  849.  *    Begin the list of the shell bindings
  850.  */
  851. /*ARGSUSED*/
  852. Char *
  853. tw_bind_next(dir, flags)
  854.     Char *dir;
  855.     int *flags;
  856. {
  857.     char *ptr;
  858.     if (tw_bind && tw_bind->name) {
  859.     for (ptr = tw_bind->name, dir = tw_retname; (*dir++ = *ptr++) != '\0';)
  860.         continue;
  861.     tw_bind++;
  862.     return(tw_retname);
  863.     }
  864.     return NULL;
  865. } /* end tw_bind_next */
  866.  
  867.  
  868. /* tw_limit_start():
  869.  *    Begin the list of the shell limitings
  870.  */
  871. /*ARGSUSED*/
  872. void
  873. tw_limit_start(dfd, pat)
  874.     DIR *dfd;
  875.     Char *pat;
  876. {
  877.     SETDIR(dfd)
  878. #ifndef HAVENOLIMIT
  879.     tw_limit = limits;
  880. #endif /* ! HAVENOLIMIT */
  881. } /* end tw_limit_start */
  882.  
  883.  
  884. /* tw_limit_next():
  885.  *    Begin the list of the shell limitings
  886.  */
  887. /*ARGSUSED*/
  888. Char *
  889. tw_limit_next(dir, flags)
  890.     Char *dir;
  891.     int *flags;
  892. {
  893. #ifndef HAVENOLIMIT
  894.     char *ptr;
  895.     if (tw_limit && tw_limit->limname) {
  896.     for (ptr = tw_limit->limname, dir = tw_retname; 
  897.          (*dir++ = *ptr++) != '\0';)
  898.         continue;
  899.     tw_limit++;
  900.     return(tw_retname);
  901.     }
  902. #endif /* ! HAVENOLIMIT */
  903.     return NULL;
  904. } /* end tw_limit_next */
  905.  
  906.  
  907. /* tw_sig_start():
  908.  *    Begin the list of the shell sigings
  909.  */
  910. /*ARGSUSED*/
  911. void
  912. tw_sig_start(dfd, pat)
  913.     DIR *dfd;
  914.     Char *pat;
  915. {
  916.     SETDIR(dfd)
  917.     tw_index = 0;
  918. } /* end tw_sig_start */
  919.  
  920.  
  921. /* tw_sig_next():
  922.  *    Begin the list of the shell sigings
  923.  */
  924. /*ARGSUSED*/
  925. Char *
  926. tw_sig_next(dir, flags)
  927.     Char *dir;
  928.     int *flags;
  929. {
  930.     char *ptr;
  931.     for (;tw_index < NSIG; tw_index++) {
  932.  
  933.     if (mesg[tw_index].iname == NULL)
  934.         continue;
  935.  
  936.     for (ptr = mesg[tw_index].iname, dir = tw_retname; 
  937.          (*dir++ = *ptr++) != '\0';)
  938.         continue;
  939.     tw_index++;
  940.     return(tw_retname);
  941.     }
  942.     return NULL;
  943. } /* end tw_sig_next */
  944.  
  945.  
  946. /* tw_job_start():
  947.  *    Begin the list of the shell jobings
  948.  */
  949. /*ARGSUSED*/
  950. void
  951. tw_job_start(dfd, pat)
  952.     DIR *dfd;
  953.     Char *pat;
  954. {
  955.     SETDIR(dfd)
  956.     tw_index = 1;
  957. } /* end tw_job_start */
  958.  
  959.  
  960. /* tw_job_next():
  961.  *    Begin the list of the shell jobings
  962.  */
  963. /*ARGSUSED*/
  964. Char *
  965. tw_job_next(dir, flags)
  966.     Char *dir;
  967.     int *flags;
  968. {
  969.     Char *ptr;
  970.     struct process *j;
  971.     for (;tw_index <= pmaxindex; tw_index++) {
  972.     for (j = proclist.p_next; j != NULL; j = j->p_next)
  973.         if (j->p_index == tw_index && j->p_procid == j->p_jobid)
  974.         break;
  975.     if (j == NULL) 
  976.         continue;
  977.     for (ptr = j->p_command, dir = tw_retname; (*dir++ = *ptr++) != '\0';)
  978.         continue;
  979.     *dir = '\0';
  980.     tw_index++;
  981.     return(tw_retname);
  982.     }
  983.     return NULL;
  984. } /* end tw_job_next */
  985.